unit uThreads;

interface

uses
  Classes;

type
  // this thread always release successfully.
  TThreadDoNothingButSleep = class(TThread)
  private

  protected
    procedure Execute; override;
  public
    constructor Create;
    destructor Destroy; override;
  end;

  // some methods invoked by execute should wrapped in Synchroniz
  // or thread will lock when releasing
  TThreadSendsCopyData = class(TThread)
  private
    FHandle: THandle;
  protected
    procedure Execute; override;
    procedure SendCopyData;
  public
    constructor Create(AHandle: THandle); overload;
    destructor Destroy; override;
  end;

implementation

uses
  Windows, Messages, SysUtils;

{ TThreadDoNothingButSleep }

constructor TThreadDoNothingButSleep.Create;
begin
  inherited Create(True);

end;

destructor TThreadDoNothingButSleep.Destroy;
begin

  inherited;
end;

procedure TThreadDoNothingButSleep.Execute;
begin
  inherited;
  while not Terminated do
  begin
    Sleep(200);
  end;
end;

{ TThreadSendsCopyData }

constructor TThreadSendsCopyData.Create(AHandle: THandle);
begin
  FHandle := AHandle;
  inherited Create(True);
end;

destructor TThreadSendsCopyData.Destroy;
begin
  FHandle := 0;
  inherited;
end;

procedure TThreadSendsCopyData.Execute;
begin
  while not Terminated do
  begin
    // send message(like wm_copydata) must be wrapped in Synchronize
    // or thread will deadlock when releasing
    // pricisely, in the last mathod -- waitfor 
//    Synchronize(SendCopyData);

    // !! DO NOT INVOKE DIRECTORLLY
    // Wired. Nothing bad happens on Win7 X64 while deadlock raised on WinXP X86.
    SendCopyData;
    
    Sleep(500);
  end;
end;

procedure TThreadSendsCopyData.SendCopyData;
var
  sInfo: String;
  vCDS: TCopyDataStruct;
begin
  sInfo := 'This is ' + ClassName;
  with vCDS do
  begin
    cbData := Length(sInfo);
    dwData := 0;
    lpData := PChar(sInfo);
  end;
  SendMessage(FHandle, WM_COPYDATA, 0, lParam(@vCDS));
end;

end.
